import {Layout} from '../../src/Layout';
export default Layout;

import docs from 'docs:@react-spectrum/s2';

export const section = 'Guides';
export const tags = ['collections'];
export const description = 'How to handle selection.';

# Selection

<PageDescription>Many collection components support selecting items by clicking or tapping them, or by using the keyboard. Learn how to handle selection events, how to control selection programmatically, and the data structures used to represent a selection.</PageDescription>

## Multiple selection

Most collection components support item selection, which is handled by the `onSelectionChange` event. Use the `selectedKeys` prop to control the selected items programmatically, or `defaultSelectedKeys` for uncontrolled behavior.

Selection is represented by a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) containing the `id` of each selected item. You can also pass any iterable collection (e.g. an array) to the `selectedKeys` and `defaultSelectedKeys` props, but the `onSelectionChange` event will always pass back a Set.

<ExampleSwitcher type="component" examples={['CardView', 'Menu', 'SelectBoxGroup', 'TableView', 'TagGroup', 'ToggleButtonGroup', 'TreeView']}>

```tsx render type="s2"
"use client";
import {CardView, AssetCard, CardPreview, Image, Content, Text, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['lion']));

  return (
    <div>
      <CardView
        aria-label="Nature photos"
        ///- begin highlight -///
        selectionMode="multiple"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
        styles={style({width: 360, height: 520})}
      >
        <AssetCard id="desert" textValue="Desert Sunset">
          <CardPreview>
            <Image src="https://images.unsplash.com/photo-1705034598432-1694e203cdf3?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={400} />
          </CardPreview>
          <Content>
            <Text slot="title">Desert Sunset</Text>
            <Text slot="description">PNG • 2/3/2024</Text>
          </Content>
        </AssetCard>
        <AssetCard id="hiking" textValue="Hiking Trail">
          <CardPreview>
            <Image src="https://images.unsplash.com/photo-1722233987129-61dc344db8b6?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
          </CardPreview>
          <Content>
            <Text slot="title">Hiking Trail</Text>
            <Text slot="description">JPEG • 1/10/2022</Text>
          </Content>
        </AssetCard>
        <AssetCard id="lion" textValue="Lion">
          <CardPreview>
            <Image src="https://images.unsplash.com/photo-1629812456605-4a044aa38fbc?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={899} />
          </CardPreview>
          <Content>
            <Text slot="title">Lion</Text>
            <Text slot="description">JPEG • 8/28/2021</Text>
          </Content>
        </AssetCard>
        <AssetCard id="mountain" textValue="Mountain Sunrise">
          <CardPreview>
            <Image src="https://images.unsplash.com/photo-1722172118908-1a97c312ce8c?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
          </CardPreview>
          <Content>
            <Text slot="title">Mountain Sunrise</Text>
            <Text slot="description">PNG • 3/15/2015</Text>
          </Content>
        </AssetCard>
      </CardView>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {Menu, MenuTrigger, MenuItem, ActionButton, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['rulers']));

  return (
    <div className={style({width: 'full', display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center'})}>
      <MenuTrigger>
        <ActionButton>View</ActionButton>
        <Menu
          ///- begin highlight -///
          selectionMode="multiple"
          selectedKeys={selectedKeys}
          onSelectionChange={setSelectedKeys}
          ///- end highlight -///
        >
          <MenuItem id="grid">Pixel grid</MenuItem>
          <MenuItem id="rulers">Rulers</MenuItem>
          <MenuItem id="layout">Layout guides</MenuItem>
          <MenuItem id="toolbar">Toolbar</MenuItem>
        </Menu>
      </MenuTrigger>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {SelectBoxGroup, SelectBox, Text, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';
import Server from '@react-spectrum/s2/illustrations/linear/Server';
import StarFilled from '@react-spectrum/s2/illustrations/linear/Star';
import AlertNotice from '@react-spectrum/s2/illustrations/linear/AlertNotice';
import PaperAirplane from '@react-spectrum/s2/illustrations/linear/Paperairplane';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['aws']));

  return (
    <div className={style({width: 'full', display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center'})}>
      <SelectBoxGroup
        aria-label="Cloud providers"
        ///- begin highlight -///
        selectionMode="multiple"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
        styles={style({width: 'full'})}
      >
        <SelectBox id="aws" textValue="AWS">
          <Server />
          <Text slot="label">Amazon Web Services</Text>
        </SelectBox>
        <SelectBox id="azure" textValue="Azure">
          <AlertNotice />
          <Text slot="label">Microsoft Azure</Text>
        </SelectBox>
        <SelectBox id="gcp" textValue="GCP">
          <StarFilled />
          <Text slot="label">Google Cloud Platform</Text>
        </SelectBox>
      </SelectBoxGroup>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {TableView, TableHeader, Column, TableBody, Row, Cell, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

///- begin collapse -///
const rows = [
  {id: 'lettuce', name: 'Lettuce', type: 'Vegetable', calories: 4},
  {id: 'tomato', name: 'Tomato', type: 'Vegetable', calories: 5},
  {id: 'cheese', name: 'Cheddar', type: 'Cheese', calories: 113},
  {id: 'tuna', name: 'Tuna salad', type: 'Salad', calories: 187},
  {id: 'egg', name: 'Egg salad', type: 'Salad', calories: 200},
  {id: 'ham', name: 'Ham', type: 'Meat', calories: 205}
];
///- end collapse -///

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['cheese']));

  return (
    <div>
      <TableView
        aria-label="Sandwich contents"
        ///- begin highlight -///
        selectionMode="multiple"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
        styles={style({width: 'full'})}
      >
        <TableHeader>
          <Column isRowHeader>Name</Column>
          <Column>Type</Column>
          <Column>Calories</Column>
        </TableHeader>
        <TableBody items={rows}>
          {item => (
            <Row>
              <Cell>{item.name}</Cell>
              <Cell>{item.type}</Cell>
              <Cell>{item.calories}</Cell>
            </Row>
          )}
        </TableBody>
      </TableView>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {TagGroup, Tag, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['cheese']));

  return (
    <div>
      <TagGroup
        label="Sandwich contents"
        ///- begin highlight -///
        selectionMode="multiple"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
      >
        <Tag id="lettuce">Lettuce</Tag>
        <Tag id="tomato">Tomato</Tag>
        <Tag id="cheese">Cheese</Tag>
        <Tag id="tuna">Tuna Salad</Tag>
        <Tag id="egg">Egg Salad</Tag>
        <Tag id="ham">Ham</Tag>
      </TagGroup>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {ToggleButtonGroup, ToggleButton, Text, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';
import TextBold from '@react-spectrum/s2/icons/TextBold';
import TextItalic from '@react-spectrum/s2/icons/TextItalic';
import TextUnderline from '@react-spectrum/s2/icons/TextUnderline';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['bold']));

  return (
    <div>
      <ToggleButtonGroup
        aria-label="Text style"
        ///- begin highlight -///
        selectionMode="multiple"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
      >
        <ToggleButton id="bold">
          <TextBold />
          <Text>Bold</Text>
        </ToggleButton>
        <ToggleButton id="italic">
          <TextItalic />
          <Text>Italic</Text>
        </ToggleButton>
        <ToggleButton id="underline">
          <TextUnderline />
          <Text>Underline</Text>
        </ToggleButton>
      </ToggleButtonGroup>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {TreeView, TreeViewItem, TreeViewItemContent, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['project']));

  return (
    <div>
      <TreeView
        aria-label="Files"
        defaultExpandedKeys={['documents', 'photos', 'project']}
        ///- begin highlight -///
        selectionMode="multiple"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
        styles={style({height: 250, width: 360})}
      >
        <TreeViewItem id="documents" textValue="Documents">
          <TreeViewItemContent>Documents</TreeViewItemContent>
          <TreeViewItem id="project" textValue="Project">
            <TreeViewItemContent>Project</TreeViewItemContent>
            <TreeViewItem id="weekly-report" textValue="Weekly Report">
              <TreeViewItemContent>Weekly Report</TreeViewItemContent>
            </TreeViewItem>
          </TreeViewItem>
        </TreeViewItem>
        <TreeViewItem id="photos" textValue="Photos">
          <TreeViewItemContent>Photos</TreeViewItemContent>
          <TreeViewItem id="image-1" textValue="Image 1">
            <TreeViewItemContent>Image 1</TreeViewItemContent>
          </TreeViewItem>
          <TreeViewItem id="image-2" textValue="Image 2">
            <TreeViewItemContent>Image 2</TreeViewItemContent>
          </TreeViewItem>
        </TreeViewItem>
      </TreeView>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

</ExampleSwitcher>

### Select all

Some components support a checkbox to select all items in the collection, or a keyboard shortcut like <Keyboard>⌘ Cmd</Keyboard> + <Keyboard>A</Keyboard>. This represents a selection of all items in the collection, regardless of whether or not all items have been loaded from the network. For example, when using a component with infinite scrolling support, the user will be unaware that all items are not yet loaded. For this reason, it makes sense for select all to represent all items, not just the loaded ones.

When a select all event occurs, `onSelectionChange` is called with the string `"all"` rather than a set of selected keys. `selectedKeys`
and `defaultSelectedKeys` can also be set to `"all"` to programmatically select all items. The application must adjust its handling of bulk actions in this case to apply to the entire collection rather than only the keys available to it locally.

```tsx render type="s2"
"use client";
import {TableView, TableHeader, Column, TableBody, Row, Cell} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

///- begin collapse -///
const rows = [
  {name: 'Games', date: '6/7/2020', type: 'File folder'},
  {name: 'Program Files', date: '4/7/2021', type: 'File folder'},
  {name: 'bootmgr', date: '11/20/2010', type: 'System file'},
  {name: 'log.txt', date: '1/18/2016', type: 'Text Document'}
];
///- end collapse -///

function Example() {
  let [selectedKeys, setSelectedKeys] = useState(new Set());

  ///- begin highlight -///
  function performBulkAction() {
    if (selectedKeys === 'all') {
      // perform action on all items
    } else {
      // perform action on selected items in selectedKeys
    }
  }
  ///- end highlight -///

  ///- begin collapse -///
  return (
    <div>
      <TableView
        aria-label="Files"
        selectionMode="multiple"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        styles={style({width: 'full'})}>
        <TableHeader>
          <Column isRowHeader>Name</Column>
          <Column>Type</Column>
          <Column>Date Modified</Column>
        </TableHeader>
        <TableBody items={rows}>
          {item => (
            <Row id={item.name}>
              <Cell>{item.name}</Cell>
              <Cell>{item.type}</Cell>
              <Cell>{item.date}</Cell>
            </Row>
          )}
        </TableBody>
      </TableView>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
  ///- end collapse -///
}
```

## Single selection

In components which support multiple selection, you can limit the selection to a single item using the
`selectionMode` prop. This continues to accept `selectedKeys` and `defaultSelectedKeys` as a `Set`, but it will
only contain a single id at a time.

ComboBox, SegmentedControl, and Tabs only support single selection and use the `selectedKey` prop (singular) rather than `selectedKeys`.

<ExampleSwitcher type="component" examples={['CardView', 'ComboBox', 'Menu', 'SegmentedControl', 'SelectBoxGroup', 'TableView', 'Tabs', 'TagGroup', 'ToggleButtonGroup', 'TreeView']}>

```tsx render type="s2"
"use client";
import {CardView, AssetCard, CardPreview, Image, Content, Text, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['lion']));

  return (
    <div>
      <CardView
        aria-label="Nature photos"
        ///- begin highlight -///
        selectionMode="single"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
        styles={style({width: 360, height: 320})}
      >
        <AssetCard id="desert" textValue="Desert Sunset">
          <CardPreview>
            <Image src="https://images.unsplash.com/photo-1705034598432-1694e203cdf3?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={400} />
          </CardPreview>
          <Content>
            <Text slot="title">Desert Sunset</Text>
            <Text slot="description">PNG • 2/3/2024</Text>
          </Content>
        </AssetCard>
        <AssetCard id="hiking" textValue="Hiking Trail">
          <CardPreview>
            <Image src="https://images.unsplash.com/photo-1722233987129-61dc344db8b6?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
          </CardPreview>
          <Content>
            <Text slot="title">Hiking Trail</Text>
            <Text slot="description">JPEG • 1/10/2022</Text>
          </Content>
        </AssetCard>
        <AssetCard id="lion" textValue="Lion">
          <CardPreview>
            <Image src="https://images.unsplash.com/photo-1629812456605-4a044aa38fbc?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={899} />
          </CardPreview>
          <Content>
            <Text slot="title">Lion</Text>
            <Text slot="description">JPEG • 8/28/2021</Text>
          </Content>
        </AssetCard>
        <AssetCard id="mountain" textValue="Mountain Sunrise">
          <CardPreview>
            <Image src="https://images.unsplash.com/photo-1722172118908-1a97c312ce8c?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
          </CardPreview>
          <Content>
            <Text slot="title">Mountain Sunrise</Text>
            <Text slot="description">PNG • 3/15/2015</Text>
          </Content>
        </AssetCard>
      </CardView>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {ComboBox, ComboBoxItem, type Key} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKey, setSelectedKey] = useState<Key>('kangaroo');

  return (
    <div>
      <ComboBox
        label="Favorite Animal"
        placeholder="Select an animal"
        ///- begin highlight -///
        selectedKey={selectedKey}
        onSelectionChange={setSelectedKey}
        ///- end highlight -///
      >
        <ComboBoxItem id="koala">Koala</ComboBoxItem>
        <ComboBoxItem id="kangaroo">Kangaroo</ComboBoxItem>
        <ComboBoxItem id="platypus">Platypus</ComboBoxItem>
        <ComboBoxItem id="eagle">Bald Eagle</ComboBoxItem>
        <ComboBoxItem id="bison">Bison</ComboBoxItem>
        <ComboBoxItem id="skunk">Skunk</ComboBoxItem>
      </ComboBox>
      <p className={style({font: 'body'})}>selectedKey: {selectedKey}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {Menu, MenuTrigger, MenuItem, ActionButton, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['grid']));

  return (
    <div className={style({width: 'full', display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center'})}>
      <MenuTrigger>
        <ActionButton>View</ActionButton>
        <Menu
          ///- begin highlight -///
          selectionMode="single"
          selectedKeys={selectedKeys}
          onSelectionChange={setSelectedKeys}
          ///- end highlight -///
        >
          <MenuItem id="grid">Pixel grid</MenuItem>
          <MenuItem id="rulers">Rulers</MenuItem>
          <MenuItem id="layout">Layout guides</MenuItem>
          <MenuItem id="toolbar">Toolbar</MenuItem>
        </Menu>
      </MenuTrigger>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {SegmentedControl, SegmentedControlItem, type Key} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKey, setSelectedKey] = useState<Key>('month');

  return (
    <div>
      <SegmentedControl
        aria-label="Time granularity"
        ///- begin highlight -///
        selectedKey={selectedKey}
        onSelectionChange={setSelectedKey}
        ///- end highlight -///
      >
        <SegmentedControlItem id="day">Day</SegmentedControlItem>
        <SegmentedControlItem id="week">Week</SegmentedControlItem>
        <SegmentedControlItem id="month">Month</SegmentedControlItem>
        <SegmentedControlItem id="year">Year</SegmentedControlItem>
      </SegmentedControl>
      <p className={style({font: 'body'})}>selectedKey: {selectedKey}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {SelectBoxGroup, SelectBox, Text, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';
import Server from '@react-spectrum/s2/illustrations/linear/Server';
import StarFilled from '@react-spectrum/s2/illustrations/linear/Star';
import AlertNotice from '@react-spectrum/s2/illustrations/linear/AlertNotice';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['aws']));

  return (
    <div className={style({width: 'full', display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center'})}>
      <SelectBoxGroup
        aria-label="Cloud provider"
        ///- begin highlight -///
        selectionMode="single"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
        styles={style({width: 'full'})}
      >
        <SelectBox id="aws" textValue="AWS">
          <Server />
          <Text slot="label">Amazon Web Services</Text>
        </SelectBox>
        <SelectBox id="azure" textValue="Azure">
          <AlertNotice />
          <Text slot="label">Microsoft Azure</Text>
        </SelectBox>
        <SelectBox id="gcp" textValue="GCP">
          <StarFilled />
          <Text slot="label">Google Cloud Platform</Text>
        </SelectBox>
      </SelectBoxGroup>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {TableView, TableHeader, Column, TableBody, Row, Cell, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

///- begin collapse -///
const rows = [
  {id: 'lettuce', name: 'Lettuce', type: 'Vegetable'},
  {id: 'tomato', name: 'Tomato', type: 'Vegetable'},
  {id: 'cheese', name: 'Cheddar', type: 'Cheese'},
  {id: 'tuna', name: 'Tuna salad', type: 'Salad'}
];
///- end collapse -///

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['cheese']));

  return (
    <div>
      <TableView
        aria-label="Sandwich contents"
        ///- begin highlight -///
        selectionMode="single"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
        styles={style({width: 'full'})}
      >
        <TableHeader>
          <Column isRowHeader>Name</Column>
          <Column>Type</Column>
        </TableHeader>
        <TableBody items={rows}>
          {item => (
            <Row>
              <Cell>{item.name}</Cell>
              <Cell>{item.type}</Cell>
            </Row>
          )}
        </TableBody>
      </TableView>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {Tabs, TabList, Tab, TabPanel, type Key} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKey, setSelectedKey] = useState<Key>('files');

  return (
    <div>
      <Tabs
        aria-label="Tabs"
        ///- begin highlight -///
        selectedKey={selectedKey}
        onSelectionChange={setSelectedKey}
        ///- end highlight -///
      >
        <TabList>
          <Tab id="home">Home</Tab>
          <Tab id="files">Files</Tab>
          <Tab id="settings">Settings</Tab>
        </TabList>
        <TabPanel id="home">Home content</TabPanel>
        <TabPanel id="files">Files content</TabPanel>
        <TabPanel id="settings">Settings content</TabPanel>
      </Tabs>
      <p className={style({font: 'body'})}>selectedKey: {selectedKey}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {TagGroup, Tag, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['cheese']));

  return (
    <div>
      <TagGroup
        label="Sandwich contents"
        ///- begin highlight -///
        selectionMode="single"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
      >
        <Tag id="lettuce">Lettuce</Tag>
        <Tag id="tomato">Tomato</Tag>
        <Tag id="cheese">Cheese</Tag>
        <Tag id="tuna">Tuna Salad</Tag>
      </TagGroup>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {ToggleButtonGroup, ToggleButton, Text, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';
import AlignLeft from '@react-spectrum/s2/icons/AlignLeft';
import AlignCenter from '@react-spectrum/s2/icons/AlignCenter';
import AlignRight from '@react-spectrum/s2/icons/AlignRight';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['left']));

  return (
    <div>
      <ToggleButtonGroup
        aria-label="Text alignment"
        ///- begin highlight -///
        selectionMode="single"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
      >
        <ToggleButton id="left">
          <AlignLeft />
          <Text>Left</Text>
        </ToggleButton>
        <ToggleButton id="center">
          <AlignCenter />
          <Text>Center</Text>
        </ToggleButton>
        <ToggleButton id="right">
          <AlignRight />
          <Text>Right</Text>
        </ToggleButton>
      </ToggleButtonGroup>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

```tsx render type="s2"
"use client";
import {TreeView, TreeViewItem, TreeViewItemContent, type Selection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['documents']));

  return (
    <div>
      <TreeView
        aria-label="Files"
        defaultExpandedKeys={['documents', 'photos']}
        ///- begin highlight -///
        selectionMode="single"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
        ///- end highlight -///
        styles={style({height: 250, width: 360})}
      >
        <TreeViewItem id="documents" textValue="Documents">
          <TreeViewItemContent>Documents</TreeViewItemContent>
          <TreeViewItem id="project" textValue="Project">
            <TreeViewItemContent>Project</TreeViewItemContent>
          </TreeViewItem>
        </TreeViewItem>
        <TreeViewItem id="photos" textValue="Photos">
          <TreeViewItemContent>Photos</TreeViewItemContent>
          <TreeViewItem id="image1" textValue="Image 1">
            <TreeViewItemContent>Image 1</TreeViewItemContent>
          </TreeViewItem>
        </TreeViewItem>
      </TreeView>
      <p className={style({font: 'body'})}>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}
```

</ExampleSwitcher>

## Item actions

In addition to selection, some collection components support item actions via the `onAction` prop. When nothing is selected, clicking, tapping, or pressing the <Keyboard>Enter</Keyboard> key triggers the item action. Items may be selected using the checkbox, or by pressing the <Keyboard>Space</Keyboard> key. When at least one item is selected, clicking or tapping a row toggles the selection.

On touch devices, actions are the primary tap interaction. Long pressing enters selection mode, which temporarily swaps the selection behavior to where tapping toggles the selection. Deselecting all items exits selection mode and reverts the selection behavior back to where tapping triggers the action. Keyboard behaviors are unaffected.

<ExampleSwitcher type="component" examples={['CardView', 'TableView', 'TreeView']}>

```tsx render wide type="s2"
"use client";
import {CardView, AssetCard, CardPreview, Image, Content, Text} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

<CardView
  aria-label="Nature photos"
  selectionMode="multiple"
  styles={style({width: 'full', height: 320})}
>
  <AssetCard
    id="desert"
    textValue="Desert Sunset"
    /*- begin highlight -*/
    onAction={() => alert('Opening Desert Sunset')}>
    {/*- end highlight -*/}
    <CardPreview>
      <Image src="https://images.unsplash.com/photo-1705034598432-1694e203cdf3?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={400} />
    </CardPreview>
    <Content>
      <Text slot="title">Desert Sunset</Text>
      <Text slot="description">PNG • 2/3/2024</Text>
    </Content>
  </AssetCard>
  <AssetCard
    id="hiking"
    textValue="Hiking Trail"
    onAction={() => alert('Opening Hiking Trail')}>
    <CardPreview>
      <Image src="https://images.unsplash.com/photo-1722233987129-61dc344db8b6?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
    </CardPreview>
    <Content>
      <Text slot="title">Hiking Trail</Text>
      <Text slot="description">JPEG • 1/10/2022</Text>
    </Content>
  </AssetCard>
  <AssetCard
    id="lion"
    textValue="Lion"
    onAction={() => alert('Opening Lion')}>
    <CardPreview>
      <Image src="https://images.unsplash.com/photo-1629812456605-4a044aa38fbc?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={899} />
    </CardPreview>
    <Content>
      <Text slot="title">Lion</Text>
      <Text slot="description">JPEG • 8/28/2021</Text>
    </Content>
  </AssetCard>
</CardView>
```

```tsx render wide type="s2"
"use client";
import {TableView, TableHeader, Column, Row, TableBody, Cell} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

<TableView
  aria-label="Table"
  selectionMode="multiple"
  styles={style({width: 'full'})}>
  <TableHeader>
    <Column isRowHeader>Name</Column>
    <Column>Type</Column>
    <Column>Date Modified</Column>
  </TableHeader>
  <TableBody>
    {/*- begin highlight -*/}
    <Row onAction={() => alert('Opening Games')}>
    {/*- end highlight -*/}
      <Cell>Games</Cell>
      <Cell>File folder</Cell>
      <Cell>6/7/2020</Cell>
    </Row>
    <Row onAction={() => alert('Opening Documents')}>
      <Cell>Documents</Cell>
      <Cell>File folder</Cell>
      <Cell>4/7/2021</Cell>
    </Row>
    <Row onAction={() => alert('Opening Photos')}>
      <Cell>Photos</Cell>
      <Cell>File folder</Cell>
      <Cell>11/20/2010</Cell>
    </Row>
  </TableBody>
</TableView>
```

```tsx render wide type="s2"
"use client";
import {TreeView, TreeViewItem, TreeViewItemContent} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

<TreeView
  aria-label="Files"
  selectionMode="multiple"
  defaultExpandedKeys={['computer']}
  styles={style({height: 250, width: 360})}>
  <TreeViewItem id="computer" textValue="My Computer">
    <TreeViewItemContent>My Computer</TreeViewItemContent>
    <TreeViewItem
      textValue="Games"
      /*- begin highlight -*/
      onAction={() => alert('Opening Games')} >
      {/*- end highlight -*/}
      <TreeViewItemContent>Games</TreeViewItemContent>
    </TreeViewItem>
    <TreeViewItem
      textValue="Documents"
      onAction={() => alert('Opening Documents')} >
      <TreeViewItemContent>Documents</TreeViewItemContent>
    </TreeViewItem>
    <TreeViewItem
      textValue="Photos"
      onAction={() => alert('Opening Photos')} >
      <TreeViewItemContent>Photos</TreeViewItemContent>
    </TreeViewItem>
  </TreeViewItem>
</TreeView>
```

</ExampleSwitcher>

In dynamic collections, it may be more convenient to use the `onAction` prop at the collection level instead of on individual items. This receives the id of the pressed item.

<ExampleSwitcher type="component" examples={['CardView', 'TableView', 'TreeView']}>

```tsx render wide type="s2"
"use client";
import {CardView, AssetCard, CardPreview, Image, Content, Text} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

///- begin collapse -///
const photos = [
  {id: 'desert', title: 'Desert Sunset', description: 'PNG • 2/3/2024', image: 'https://images.unsplash.com/photo-1705034598432-1694e203cdf3?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', width: 600, height: 400},
  {id: 'hiking', title: 'Hiking Trail', description: 'JPEG • 1/10/2022', image: 'https://images.unsplash.com/photo-1722233987129-61dc344db8b6?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', width: 600, height: 900},
  {id: 'lion', title: 'Lion', description: 'JPEG • 8/28/2021', image: 'https://images.unsplash.com/photo-1629812456605-4a044aa38fbc?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', width: 600, height: 899}
];
///- end collapse -///

<CardView
  aria-label="Nature photos"
  selectionMode="multiple"
  /*- begin highlight -*/
  onAction={id => alert(`Opening ${id}`)}
  /*- end highlight -*/
  styles={style({width: 'full', height: 320})}
  items={photos}>
  {photo => (
    <AssetCard id={photo.id} textValue={photo.title}>
      <CardPreview>
        <Image src={photo.image} width={photo.width} height={photo.height} />
      </CardPreview>
      <Content>
        <Text slot="title">{photo.title}</Text>
        <Text slot="description">{photo.description}</Text>
      </Content>
    </AssetCard>
  )}
</CardView>
```

```tsx render wide type="s2"
"use client";
import {TableView, TableHeader, Column, Row, TableBody, Cell} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';

///- begin collapse -///
const files = [
  {id: 'games', name: 'Games', type: 'Folder', date: '6/7/2020'},
  {id: 'documents', name: 'Documents', type: 'Folder', date: '4/7/2021'},
  {id: 'photos', name: 'Photos', type: 'Folder', date: '11/20/2010'}
];
///- end collapse -///

<TableView
  aria-label="Table"
  selectionMode="multiple"
  /*- begin highlight -*/
  onAction={id => alert(`Opening ${id}`)}
  /*- end highlight -*/
  styles={style({width: 'full'})}>
  <TableHeader>
    <Column isRowHeader>Name</Column>
    <Column>Type</Column>
    <Column>Date Modified</Column>
  </TableHeader>
  <TableBody items={files}>
    {item => (
      <Row>
        <Cell>{item.name}</Cell>
        <Cell>{item.type}</Cell>
        <Cell>{item.date}</Cell>
      </Row>
    )}
  </TableBody>
</TableView>
```

```tsx render wide type="s2"
"use client";
import {TreeView, TreeViewItem, TreeViewItemContent, Collection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

///- begin collapse -///
const files = [
  {id: 'games', name: 'Games'},
  {id: 'documents', name: 'Documents'},
  {id: 'photos', name: 'Photos'}
];
///- end collapse -///

<TreeView
  aria-label="Files"
  selectionMode="multiple"
  defaultExpandedKeys={['computer']}
  /*- begin highlight -*/
  onAction={id => alert(`Opening ${id}`)}
  /*- end highlight -*/
  styles={style({height: 250, width: 360})}>
  <TreeViewItem id="computer" textValue="My Computer">
    <TreeViewItemContent>My Computer</TreeViewItemContent>
    <Collection items={files}>
      {item => (
        <TreeViewItem textValue={item.name}>
          <TreeViewItemContent>{item.name}</TreeViewItemContent>
        </TreeViewItem>
      )}
    </Collection>
  </TreeViewItem>
</TreeView>
```

</ExampleSwitcher>

## Disabled items

An item can be disabled with the `isDisabled` prop. By default, disabled items are not focusable, selectable, or actionable. When `disabledBehavior="selection"`, only selection is disabled.

<ExampleSwitcher type="component" examples={['CardView', 'ComboBox', 'Menu', 'SegmentedControl', 'SelectBoxGroup', 'TableView', 'Tabs', 'TagGroup', 'ToggleButtonGroup', 'TreeView']}>

```tsx render wide type="s2"
"use client";
import {CardView, AssetCard, CardPreview, Image, Content, Text} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

<CardView
  aria-label="Pokemon"
  selectionMode="multiple"
  styles={style({width: 'full', height: 320})}
>
  <AssetCard id="charizard" textValue="Charizard">
    <CardPreview>
      <Image src="https://img.pokemondb.net/sprites/home/normal/2x/avif/charizard.avif" />
    </CardPreview>
    <Content>
      <Text slot="title">Charizard</Text>
      <Text slot="description">Fire, Flying • Level 67</Text>
    </Content>
  </AssetCard>
  <AssetCard id="blastoise" textValue="Blastoise">
    <CardPreview>
      <Image src="https://img.pokemondb.net/sprites/home/normal/2x/avif/blastoise.avif" />
    </CardPreview>
    <Content>
      <Text slot="title">Blastoise</Text>
      <Text slot="description">Water • Level 56</Text>
    </Content>
  </AssetCard>
  {/*- begin highlight -*/}
  <AssetCard id="venusaur" textValue="Venusaur" isDisabled>
  {/*- end highlight -*/}
    <CardPreview>
      <Image src="https://img.pokemondb.net/sprites/home/normal/2x/avif/venusaur.avif" />
    </CardPreview>
    <Content>
      <Text slot="title">Venusaur</Text>
      <Text slot="description">Grass, Poison • Level 83</Text>
    </Content>
  </AssetCard>
  <AssetCard id="pikachu" textValue="Pikachu">
    <CardPreview>
      <Image src="https://img.pokemondb.net/sprites/home/normal/2x/avif/pikachu.avif" />
    </CardPreview>
    <Content>
      <Text slot="title">Pikachu</Text>
      <Text slot="description">Electric • Level 100</Text>
    </Content>
  </AssetCard>
</CardView>
```

```tsx render wide type="s2"
"use client";
import {ComboBox, ComboBoxItem} from '@react-spectrum/s2';

<ComboBox
  label="Pokemon"
  placeholder="Select a Pokemon"
  defaultSelectedKey="pikachu"
>
  <ComboBoxItem id="charizard">Charizard</ComboBoxItem>
  <ComboBoxItem id="blastoise">Blastoise</ComboBoxItem>
  {/*- begin highlight -*/}
  <ComboBoxItem id="venusaur" isDisabled>Venusaur</ComboBoxItem>
  {/*- end highlight -*/}
  <ComboBoxItem id="pikachu">Pikachu</ComboBoxItem>
</ComboBox>
```

```tsx render wide type="s2"
"use client";
import {Menu, MenuTrigger, MenuItem, ActionButton} from '@react-spectrum/s2';

<MenuTrigger>
  <ActionButton>Pokemon</ActionButton>
  <Menu selectionMode="multiple" defaultSelectedKeys={['pikachu']}>
    <MenuItem id="charizard">Charizard</MenuItem>
    <MenuItem id="blastoise">Blastoise</MenuItem>
    {/*- begin highlight -*/}
    <MenuItem id="venusaur" isDisabled>Venusaur</MenuItem>
    {/*- end highlight -*/}
    <MenuItem id="pikachu">Pikachu</MenuItem>
  </Menu>
</MenuTrigger>
```

```tsx render wide type="s2"
"use client";
import {SegmentedControl, SegmentedControlItem} from '@react-spectrum/s2';

<SegmentedControl aria-label="Time granularity" defaultSelectedKey="month">
  <SegmentedControlItem id="day">Day</SegmentedControlItem>
  {/*- begin highlight -*/}
  <SegmentedControlItem id="week" isDisabled>Week</SegmentedControlItem>
  {/*- end highlight -*/}
  <SegmentedControlItem id="month">Month</SegmentedControlItem>
  <SegmentedControlItem id="year">Year</SegmentedControlItem>
</SegmentedControl>
```

```tsx render wide type="s2"
"use client";
import {SelectBoxGroup, SelectBox, Text} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import Server from '@react-spectrum/s2/illustrations/linear/Server';
import StarFilled from '@react-spectrum/s2/illustrations/linear/Star';
import AlertNotice from '@react-spectrum/s2/illustrations/linear/AlertNotice';
import PaperAirplane from '@react-spectrum/s2/illustrations/linear/Paperairplane';

<SelectBoxGroup
  aria-label="Cloud providers"
  selectionMode="multiple"
  defaultSelectedKeys={['aws']}
  styles={style({width: 'full'})}
>
  <SelectBox id="aws" textValue="AWS">
    <Server />
    <Text slot="label">Amazon Web Services</Text>
  </SelectBox>
  <SelectBox id="azure" textValue="Azure">
    <AlertNotice />
    <Text slot="label">Microsoft Azure</Text>
  </SelectBox>
  {/*- begin highlight -*/}
  <SelectBox id="gcp" textValue="GCP" isDisabled>
  {/*- end highlight -*/}
    <StarFilled />
    <Text slot="label">Google Cloud Platform</Text>
  </SelectBox>
</SelectBoxGroup>
```

```tsx render wide type="s2"
import {TableView, TableHeader, Column, Row, TableBody, Cell} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

<TableView
  aria-label="Pokemon"
  selectionMode="multiple"
  styles={style({width: 'full'})}>
  <TableHeader>
    <Column isRowHeader>Name</Column>
    <Column>Type</Column>
    <Column>Level</Column>
  </TableHeader>
  <TableBody>
    <Row id="charizard">
      <Cell>Charizard</Cell>
      <Cell>Fire, Flying</Cell>
      <Cell>67</Cell>
    </Row>
    <Row id="blastoise">
      <Cell>Blastoise</Cell>
      <Cell>Water</Cell>
      <Cell>56</Cell>
    </Row>
    {/*- begin highlight -*/}
    <Row id="venusaur" isDisabled>
    {/*- end highlight -*/}
      <Cell>Venusaur</Cell>
      <Cell>Grass, Poison</Cell>
      <Cell>83</Cell>
    </Row>
    <Row id="pikachu">
      <Cell>Pikachu</Cell>
      <Cell>Electric</Cell>
      <Cell>100</Cell>
    </Row>
  </TableBody>
</TableView>
```

```tsx render wide type="s2"
"use client";
import {Tabs, TabList, Tab, TabPanel} from '@react-spectrum/s2';

<Tabs aria-label="Tabs" defaultSelectedKey="files">
  <TabList>
    <Tab id="home">Home</Tab>
    <Tab id="files">Files</Tab>
    {/*- begin highlight -*/}
    <Tab id="search" isDisabled>Search</Tab>
    {/*- end highlight -*/}
    <Tab id="settings">Settings</Tab>
  </TabList>
  <TabPanel id="home">Home content</TabPanel>
  <TabPanel id="files">Files content</TabPanel>
  <TabPanel id="search">Search content</TabPanel>
  <TabPanel id="settings">Settings content</TabPanel>
</Tabs>
```

```tsx render wide type="s2"
"use client";
import {TagGroup, Tag} from '@react-spectrum/s2';

<TagGroup
  label="Pokemon"
  selectionMode="multiple">
  <Tag>Charizard</Tag>
  <Tag>Blastoise</Tag>
  {/*- begin highlight -*/}
  <Tag isDisabled>Venusaur</Tag>
  {/*- end highlight -*/}
  <Tag>Pikachu</Tag>
</TagGroup>
```

```tsx render wide type="s2"
"use client";
import {ToggleButtonGroup, ToggleButton, Text} from '@react-spectrum/s2';
import TextBold from '@react-spectrum/s2/icons/TextBold';
import TextItalic from '@react-spectrum/s2/icons/TextItalic';
import TextUnderline from '@react-spectrum/s2/icons/TextUnderline';

<ToggleButtonGroup
  aria-label="Text style"
  selectionMode="multiple"
  defaultSelectedKeys={['bold']}
>
  <ToggleButton id="bold">
    <TextBold />
    <Text>Bold</Text>
  </ToggleButton>
  {/*- begin highlight -*/}
  <ToggleButton id="italic" isDisabled>
  {/*- end highlight -*/}
    <TextItalic />
    <Text>Italic</Text>
  </ToggleButton>
  <ToggleButton id="underline">
    <TextUnderline />
    <Text>Underline</Text>
  </ToggleButton>
</ToggleButtonGroup>
```

```tsx render wide type="s2"
"use client";
import {TreeView, TreeViewItem, TreeViewItemContent} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

<TreeView
  aria-label="Pokemon evolution"
  styles={style({height: 250, width: 360})}
  defaultExpandedKeys={['bulbasaur', 'ivysaur']}
  selectionMode="multiple">
  <TreeViewItem id="bulbasaur" textValue="Bulbasaur">
    <TreeViewItemContent>Bulbasaur</TreeViewItemContent>
    <TreeViewItem id="ivysaur" textValue="Ivysaur">
      <TreeViewItemContent>Ivysaur</TreeViewItemContent>
      {/*- begin highlight -*/}
      <TreeViewItem id="venusaur" textValue="Venusaur" isDisabled>
        <TreeViewItemContent>Venusaur</TreeViewItemContent>
      </TreeViewItem>
      {/*- end highlight -*/}
    </TreeViewItem>
  </TreeViewItem>
  <TreeViewItem id="charmander" textValue="Charmander">
    <TreeViewItemContent>Charmander</TreeViewItemContent>
    <TreeViewItem id="charmeleon" textValue="Charmeleon">
      <TreeViewItemContent>Charmeleon</TreeViewItemContent>
      <TreeViewItem id="charizard" textValue="Charizard">
        <TreeViewItemContent>Charizard</TreeViewItemContent>
      </TreeViewItem>
    </TreeViewItem>
  </TreeViewItem>
  <TreeViewItem id="squirtle" textValue="Squirtle">
    <TreeViewItemContent>Squirtle</TreeViewItemContent>
    <TreeViewItem id="wartortle" textValue="Wartortle">
      <TreeViewItemContent>Wartortle</TreeViewItemContent>
      <TreeViewItem id="blastoise" textValue="Blastoise">
        <TreeViewItemContent>Blastoise</TreeViewItemContent>
      </TreeViewItem>
    </TreeViewItem>
  </TreeViewItem>
</TreeView>
```

</ExampleSwitcher>

In dynamic collections, it may be more convenient to use the `disabledKeys` prop at the collection level instead of `isDisabled` on individual items. This accepts a list of item ids that are disabled.

<ExampleSwitcher type="component" examples={['CardView', 'ComboBox', 'Menu', 'SelectBoxGroup', 'TableView', 'TagGroup', 'TreeView']}>

```tsx render wide type="s2"
"use client";
import {CardView, AssetCard, CardPreview, Image, Content, Text} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

///- begin collapse -///
const items = [
  {id: 1, name: 'Charizard', type: 'Fire, Flying', level: 67},
  {id: 2, name: 'Blastoise', type: 'Water', level: 56},
  {id: 3, name: 'Venusaur', type: 'Grass, Poison', level: 83},
  {id: 4, name: 'Pikachu', type: 'Electric', level: 100}
];
///- end collapse -///

<CardView
  aria-label="Pokemon"
  selectionMode="multiple"
  ///- begin highlight -///
  disabledKeys={[3]}
  ///- end highlight -///
  styles={style({width: 'full', height: 320})}
  items={items}>
  {item => (
    <AssetCard id={item.id} textValue={item.name}>
      <CardPreview>
        <Image src={`https://img.pokemondb.net/sprites/home/normal/2x/avif/${item.name.toLowerCase()}.avif`} />
      </CardPreview>
      <Content>
        <Text slot="title">{item.name}</Text>
        <Text slot="description">{item.type} • Level {item.level}</Text>
      </Content>
    </AssetCard>
  )}
</CardView>
```

```tsx render wide type="s2"
"use client";
import {ComboBox, ComboBoxItem} from '@react-spectrum/s2';

///- begin collapse -///
const items = [
  {id: 1, name: 'Charizard'},
  {id: 2, name: 'Blastoise'},
  {id: 3, name: 'Venusaur'},
  {id: 4, name: 'Pikachu'}
];
///- end collapse -///

<ComboBox
  label="Pokemon"
  placeholder="Select a Pokemon"
  defaultSelectedKey={4}
  ///- begin highlight -///
  disabledKeys={[3]}
  ///- end highlight -///
  items={items}>
  {item => <ComboBoxItem>{item.name}</ComboBoxItem>}
</ComboBox>
```

```tsx render wide type="s2"
"use client";
import {Menu, MenuTrigger, MenuItem, ActionButton} from '@react-spectrum/s2';

///- begin collapse -///
const items = [
  {id: 1, name: 'Charizard'},
  {id: 2, name: 'Blastoise'},
  {id: 3, name: 'Venusaur'},
  {id: 4, name: 'Pikachu'}
];
///- end collapse -///

<MenuTrigger>
  <ActionButton>Pokemon</ActionButton>
  <Menu
    selectionMode="multiple"
    defaultSelectedKeys={[4]}
    ///- begin highlight -///
    disabledKeys={[3]}
    ///- end highlight -///
    items={items}>
    {item => <MenuItem>{item.name}</MenuItem>}
  </Menu>
</MenuTrigger>
```

```tsx render wide type="s2"
"use client";
import {SelectBoxGroup, SelectBox, Text} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import Server from '@react-spectrum/s2/illustrations/linear/Server';
import StarFilled from '@react-spectrum/s2/illustrations/linear/Star';
import AlertNotice from '@react-spectrum/s2/illustrations/linear/AlertNotice';
import PaperAirplane from '@react-spectrum/s2/illustrations/linear/Paperairplane';

///- begin collapse -///
const items = [
  {id: 1, name: 'AWS', illustration: <Server />},
  {id: 2, name: 'Azure', illustration: <AlertNotice />},
  {id: 3, name: 'GCP', illustration: <StarFilled />}
];
///- end collapse -///

<SelectBoxGroup
  aria-label="Cloud providers"
  selectionMode="multiple"
  defaultSelectedKeys={[1]}
  ///- begin highlight -///
  disabledKeys={[3]}
  ///- end highlight -///
  styles={style({width: 'full'})}
  items={items}>
  {item => (
    <SelectBox textValue={item.name}>
      {item.illustration}
      <Text slot="label">{item.name}</Text>
    </SelectBox>
  )}
</SelectBoxGroup>
```

```tsx render wide type="s2"
"use client";
import {TableView, TableHeader, Column, Row, TableBody, Cell} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

///- begin collapse -///
let items = [
  {id: 1, name: 'Charizard', type: 'Fire, Flying', level: 67},
  {id: 2, name: 'Blastoise', type: 'Water', level: 56},
  {id: 3, name: 'Venusaur', type: 'Grass, Poison', level: 83},
  {id: 4, name: 'Pikachu', type: 'Electric', level: 100}
];
///- end collapse -///

<TableView
  aria-label="Pokemon"
  ///- begin highlight -///
  disabledKeys={[3]}
  ///- end highlight -///
  selectionMode="multiple"
  styles={style({width: 'full'})}>
  <TableHeader>
    <Column isRowHeader>Name</Column>
    <Column>Type</Column>
    <Column>Level</Column>
  </TableHeader>
  <TableBody items={items}>
    {item => (
      <Row>
        <Cell>{item.name}</Cell>
        <Cell>{item.type}</Cell>
        <Cell>{item.level}</Cell>
      </Row>
    )}
  </TableBody>
</TableView>
```

```tsx render wide type="s2"
"use client";
import {TagGroup, Tag} from '@react-spectrum/s2';

///- begin collapse -///
const items = [
  {id: 1, name: 'Charizard'},
  {id: 2, name: 'Blastoise'},
  {id: 3, name: 'Venusaur'},
  {id: 4, name: 'Pikachu'}
];
///- end collapse -///

<TagGroup
  label="Pokemon"
  selectionMode="multiple"
  ///- begin highlight -///
  disabledKeys={[3]}
  ///- end highlight -///
  items={items}>
  {item => <Tag>{item.name}</Tag>}
</TagGroup>
```

```tsx render wide type="s2"
"use client";
import {TreeView, TreeViewItem, TreeViewItemContent, Collection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

///- begin collapse -///
let items = [
  {id: 1, name: 'Bulbasaur', type: 'Grass', level: 14, children: [
    {id: 2, name: 'Ivysaur', type: 'Grass', level: 30, children: [
      {id: 3, name: 'Venusaur', type: 'Grass', level: 83}
    ]}
  ]},
  {id: 4, name: 'Charmander', type: 'Fire', level: 16, children: [
    {id: 5, name: 'Charmeleon', type: 'Fire', level: 32, children: [
      {id: 6, name: 'Charizard', type: 'Fire, Flying', level: 67}
    ]}
  ]},
  {id: 7, name: 'Squirtle', type: 'Water', level: 8, children: [
    {id: 8, name: 'Wartortle', type: 'Water', level: 34, children: [
      {id: 9, name: 'Blastoise', type: 'Water', level: 56}
    ]}
  ]}
];
///- end collapse -///

<TreeView
  aria-label="Pokemon evolution"
  styles={style({height: 250, width: 360})}
  defaultExpandedKeys={[1, 2]}
  selectionMode="multiple"
  ///- begin highlight -///
  disabledKeys={[3]}
  ///- end highlight -///
  items={items}>
  {function renderItem(item) {
    return (
      <TreeViewItem textValue={item.name}>
        <TreeViewItemContent>{item.name}</TreeViewItemContent>
        <Collection items={item.children}>
          {renderItem}
        </Collection>
      </TreeViewItem>
    )
  }}
</TreeView>
```

</ExampleSwitcher>
